package com.yupi.yupicturebackend.manager.websocket;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.yupi.yupicturebackend.model.entity.Picture;
import com.yupi.yupicturebackend.model.entity.Space;
import com.yupi.yupicturebackend.model.entity.User;
import com.yupi.yupicturebackend.model.enums.SpaceTypeEnum;
import com.yupi.yupicturebackend.service.PictureService;
import com.yupi.yupicturebackend.service.SpaceService;
import com.yupi.yupicturebackend.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 在 websocket 建立连接前需要进行权限校验
 * 并且，在 websocket 中我们不能直接在后续收到前端消息时直接从 request 对象中获取用户登录信息
 * 因此需要通过 websocket 拦截器，为即将建立连接的 websocket 会话指定一些属性
 * 如：用户登录信息、编辑图片的ID 等
 */
@Slf4j
@Component
public class WSHandshakeInterceptor implements HandshakeInterceptor {

    @Resource
    private UserService userService;

    @Resource
    private PictureService pictureService;

    @Resource
    private SpaceService spaceService;

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        // 将 ServerHttpRequest 转换为 HttpServletRequest，获取当前登录用户信息
        HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) request).getServletRequest();
        User loginUser = userService.getLoginUser(httpServletRequest);
        // 校验当前用户
        if (ObjUtil.isEmpty(loginUser)){
            log.error("用户未登录，拒绝建立连接");
            return false;
        }
        // 获取前端传递的 pictureId
        String pictureId = httpServletRequest.getParameter("pictureId");
        if (StrUtil.isBlank(pictureId)){
            log.error("缺少图片参数，拒绝建立连接");
            return false;
        }
        // 校验当前用户是否有当前图片的编辑权限
        Picture picture = pictureService.getById(pictureId);
        if (ObjUtil.isNull(picture)){
            log.error("图片不存在，拒绝建立连接");
            return false;
        }
        // 允许 spaceId 为空，为空则为公共图库，管理员可以协同编辑
        Long spaceId = picture.getSpaceId();
        if (spaceId != null){
            Space space = spaceService.getById(spaceId);
            if (ObjUtil.isNull(space)){
                log.error("空间不存在，拒绝建立连接");
                return false;
            }
            if (!space.getSpaceType().equals(SpaceTypeEnum.TEAM.getValue())){
                // 不是团队空间而是私有空间，不需要协同编辑
                log.error("非团队空间，拒绝建立连接");
            }
        }
        // 添加 websocket 连接请求参数
        attributes.put("user", loginUser);
        attributes.put("pictureId", Long.valueOf(pictureId));
        attributes.put("userId", loginUser.getId());

        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }
}
